package com.ruoyi.app.controller;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.app.dto.PayDto;
import com.ruoyi.app.service.PayService;
import com.ruoyi.common.utils.WechatPay2ValidatorForRequest;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.utils.HttpUtils;
import com.ruoyi.common.utils.ParamMapUtils;
import com.ruoyi.common.utils.PermissionAnnotate;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.util.Objects;

/*
@description:小程序支付
@ClassName PayController
@author chen
@create 2025-03-16 22:32
@Version 1.0
*/
@Slf4j
@RestController
@RequestMapping("app")
public class PayController
{
    @Resource
    private PayService payService;
    @Resource
    private Verifier verifier;


    /*
     * @==============History===============<br/>
     * @Description //   用户提现
     * @Date 2025-4-11 18:50
     * @Author < a href="15991488967@163.com">chen</ a>
     * @return com.ruoyi.framework.web.domain.AjaxResult
     */
    @PermissionAnnotate(operateType = "支付模块", operateExplain = "用户提现", sourceType = "controller")
    @PostMapping(value = "/transfer",produces = "application/json;charset=utf-8")
    public AjaxResult transfer(@RequestBody PayDto payDto)
    {
        log.info("-----------------------用户提现接口开始处理--------------------------");
        return payService.transfer(payDto);
    }

    /*
     * @==============History===============<br/>
     * @Description //   用户下单
     * @Date 2025-3-16 22:58
     * @Author < a href="15991488967@163.com">chen</ a>
     * @return com.ruoyi.framework.web.domain.AjaxResult
     */
    @PermissionAnnotate(operateType = "支付模块", operateExplain = "用户支付", sourceType = "controller")
    @PostMapping(value = "/order",produces = "application/json;charset=utf-8")
    public AjaxResult order(@RequestBody PayDto payDto) throws Exception
    {
        log.info("-----------------------用户下单接口开始处理--------------------------");
        return payService.order(payDto);
    }



    /*
     * @==============History===============<br/>
     * @Description //
     * @Date 2025-4-11 20:43
     * @Author < a href="15991488967@163.com">chen</ a>
     * @return java.lang.String
     */
    @RequestMapping("/transferBill")
    public String transferBill(HttpServletRequest request,HttpServletResponse response)
    {

        ParamMapUtils paramMapUtils = new ParamMapUtils();
        try {
            String requestBody = HttpUtils.readData(request);

            JSONObject jsonObject = JSON.parseObject(requestBody);
            String requestId = jsonObject.getString("id");
            log.info("微信提现通知的id--------------->>>>{}",requestId);
            WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest = new WechatPay2ValidatorForRequest(verifier, requestId,requestBody);

            if (!wechatPay2ValidatorForRequest.validate(request))
            {
                log.error("----------------------微信提现通知验签失败---------------------------");
                //通知失败应答
                response.setStatus(500);
                Objects.requireNonNull(paramMapUtils.put("code", "ERROR"))
                        .put("message","通知验签失败");
                return JSON.toJSONString(paramMapUtils);
            }



            log.info("----------------------微信提现通知验签成功---------------------------");

            String plaintText = this.decryptFromResource(jsonObject);

            JSONObject plaintJsonObject = JSON.parseObject(plaintText);

            String orderNo = plaintJsonObject.getString("out_bill_no");

            log.info("--------------------------------------->>>>获取到提现订单号,{}",orderNo);


            payService.transferBill(orderNo,response,paramMapUtils);

        }catch (Exception e)
        {
            response.setStatus(500);
            Objects.requireNonNull(paramMapUtils.put("code", "ERROR")).put("message","失败");
        }
        return null;
    }




    /*
     * @==============History===============<br/>
     * @Description //   支付回调
     * @Date 2025-3-31 19:49
     * @Author < a href="15991488967@163.com">chen</ a>
     * @return com.ruoyi.framework.web.domain.AjaxResult
     */
    @RequestMapping("/pay")
    public String pay(HttpServletRequest request,HttpServletResponse response)
    {
        ParamMapUtils paramMapUtils = new ParamMapUtils();

        try {
            String body = HttpUtils.readData(request);
            log.info("微信支付开始回调通知:"+body);
            JSONObject jsonObject = JSON.parseObject(body);
            String requestId = jsonObject.getString("id");
            log.info("微信支付通知的id--------------->>>>{}",requestId);
            WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest = new WechatPay2ValidatorForRequest(verifier, requestId,body);

            if (!wechatPay2ValidatorForRequest.validate(request))
            {
                log.error("----------------------微信支付通知验签失败---------------------------");
                //通知失败应答
                response.setStatus(500);
                Objects.requireNonNull(paramMapUtils.put("code", "ERROR"))
                        .put("message","通知验签失败");
                return JSON.toJSONString(paramMapUtils);
            }

            log.info("----------------------微信支付通知验签成功---------------------------");

            String plaintText = this.decryptFromResource(jsonObject);

            JSONObject plaintJsonObject = JSON.parseObject(plaintText);

            String orderNo = plaintJsonObject.getString("out_trade_no");

            log.info("--------------------------------------->>>>获取到支付订单号,{}",orderNo);

            payService.pay(orderNo,response,paramMapUtils);

        }catch (Exception e)
        {
            // 失败应答
            response.setStatus(500);
            Objects.requireNonNull(paramMapUtils.put("code", "ERROR")).put("message","失败");
        }

        return JSON.toJSONString(paramMapUtils);
    }



    public String decryptFromResource(JSONObject jsonObject) throws GeneralSecurityException
    {
        log.info("微信支付秘文解密");

        //通知数据 resourceMap
        JSONObject resource = jsonObject.getJSONObject("resource");
        //数据秘文
        String ciphertext = resource.getString("ciphertext");
        //获取随机串
        String nonce = resource.getString("nonce");
        String associated_data = resource.getString("associated_data");

        log.info("微信支付秘文------>{}",ciphertext);
        AesUtil aesUtil = new AesUtil(Constants.API_V3KEY.getBytes(StandardCharsets.UTF_8));
        //获取明文（解密后的数据）
        String plainText = aesUtil.decryptToString(associated_data.getBytes(StandardCharsets.UTF_8),
                nonce.getBytes(StandardCharsets.UTF_8),
                ciphertext);

        log.info("微信支付明文---->{}",plainText);

        return plainText;
    }


}
